import * as THREE from 'three';
import * as dat from 'dat.gui';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export function init03(width, height) {
  // 创建一个场景，它将包含我们所有的元素，如对象，相机和灯光。
  const scene = new THREE.Scene();
  // 强制场景中的所有物体使用相同的材质
  scene.overrideMaterial = new THREE.MeshLambertMaterial({
    color: 0xffffff
  });

  // 创建一个摄像机，它定义了我们正在查看的位置。
  const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);

  // 创建一个渲染器和设置大小
  const renderer = new THREE.WebGLRenderer();
  renderer.setClearColor(new THREE.Color(0x000000));
  renderer.setSize(width, height);
  renderer.shadowMap.enabled = true;

  // 创建平面
  const planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1);
  const planeMaterial = new THREE.MeshLambertMaterial({
    color: 0xffffff
  });
  const plane = new THREE.Mesh(planeGeometry, planeMaterial);

  // 旋转并定位平面
  plane.rotation.x = -0.5 * Math.PI;
  plane.position.x = 0;
  plane.position.y = 0;
  plane.position.z = 0;
  // 接收阴影
  plane.receiveShadow = true;
  // 将平面添加到场景中
  scene.add(plane);

  // 将相机定位并指向场景的中心
  camera.position.set(-30, 40, 30);
  camera.lookAt(scene.position);

  // 添加光源
  const ambientLight = new THREE.AmbientLight(0x3c3c3c);
  scene.add(ambientLight);

  // 为阴影添加聚光灯
  const spotLight = new THREE.SpotLight(0xffffff, 1.2, 150, 120);
  spotLight.position.set(-40, 60, -10);
  spotLight.castShadow = true;
  scene.add(spotLight);

  // 视角操作
  const orbit = new OrbitControls(camera, renderer.domElement);

  // 将呈现器的输出添加到html元素中
  document.getElementById('webgl-output').appendChild(renderer.domElement);

  // 浏览器大小自适应
  window.addEventListener('resize', onResize, false);

  const controls = new (function() {
    this.rotationSpeed = 0.02;
    this.numberOfObjects = scene.children.length;

    this.addCube = function() {
      const cubeSize = Math.ceil(Math.random() * 3);
      const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
      const cubeMaterial = new THREE.MeshLambertMaterial({
        color: Math.random() * 0xffffff
      });
      const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
      cube.castShadow = true;
      cube.name = 'cube-' + scene.children.length;

      // 在场景中随机放置立方体

      cube.position.x =
        -30 + Math.round(Math.random() * planeGeometry.parameters.width);
      cube.position.y = Math.round(Math.random() * 5);
      cube.position.z =
        -20 + Math.round(Math.random() * planeGeometry.parameters.height);

      // 将立方体添加到场景中
      scene.add(cube);
      this.numberOfObjects = scene.children.length;
    };

    this.removeCube = function() {
      const allChildren = scene.children;
      const lastObject = allChildren[allChildren.length - 1];
      if (lastObject instanceof THREE.Mesh) {
        scene.remove(lastObject);
        this.numberOfObjects = scene.children.length;
      }
    };

    this.outputObjects = function() {
      console.log(scene.children);
    };
  })();

  const gui = new dat.GUI();
  gui.add(controls, 'rotationSpeed', 0, 0.5);
  gui.add(controls, 'addCube');
  gui.add(controls, 'removeCube');
  gui.add(controls, 'outputObjects');
  gui.add(controls, 'numberOfObjects').listen();

  render();

  function render() {
    // 围绕它的轴旋转所有立方体
    scene.traverse(e => {
      if (e instanceof THREE.Mesh && e != plane) {
        e.rotation.x += controls.rotationSpeed;
        e.rotation.y += controls.rotationSpeed;
        e.rotation.z += controls.rotationSpeed;
      }
    });
    orbit.update();
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }

  function onResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(width, height);
  }
}
